#include "ministerio.h"

Ministerio::Ministerio() {

	_provincias = Lista<Provincia>();
	_registro = Lista<pair<Provincia, Hotel> >();
}

Ministerio::Ministerio(const Lista<Provincia>& ps) {

	_provincias = ps;
	_registro = Lista<pair<Provincia, Hotel> >();
}

Lista<Provincia> Ministerio::secretarias() const {

	return _provincias;
}

Lista<Hotel> Ministerio::registro(const Provincia p) const {

	Lista<Hotel> res;
	int i = 0;
	while (i < _registro.longitud()) {

		if (_registro.iesimo(i).first == p)
			res.agregarAtras(_registro.iesimo(i).second);

		i++;
	}

	return res;
}

Lista<Hotel> Ministerio::getHoteles() const {

	Lista<Hotel> hoteles;
	int i = 0;

	while (i < _registro.longitud()) {

		hoteles.agregar(_registro.iesimo(i).second);
		i++;
	}

	return hoteles;
}

Lista<Lista<Hotel> > Ministerio::agregarHotel(const Hotel hotel, const Lista<Lista<Hotel> > cadenas) const {

	Lista<Lista<Hotel> > cadenasNueva;
	bool agregado = false;
	int i = 0;

	while (i < cadenas.longitud()) {

		Lista<Hotel> cadena = cadenas.iesimo(i);

		if (cadena.iesimo(0).cadena() == hotel.cadena()) {

			cadena.agregar(hotel);
			agregado = true;
		}

		cadenasNueva.agregarAtras(cadena);
		i++;
	}

	if (!agregado) {

		Lista<Hotel> cadenaNueva;
		cadenaNueva.agregar(hotel);
		cadenasNueva.agregarAtras(cadenaNueva);
	}

	return cadenasNueva;
}

Lista<Lista<Hotel> > Ministerio::cadenasDeHoteles() const {

	Lista<Lista<Hotel> > cadenas;
	Lista<Hotel> hoteles = getHoteles();
	int i = 0;

	while (i < hoteles.longitud()) {

		cadenas = agregarHotel(hoteles.iesimo(i), cadenas);
		i++;
	}

	return cadenas;
	/*Lista<Hotel> hoteles=sacarRepes(todoshoteles());
Lista<Lista<Hotel> > res;
int i=0;
while (i<listaCadenas(hoteles).longitud())
  {
      res.agregarAtras(listarhoteles(listaCadenas(hoteles).iesimo(i), hoteles));
      i++;
  }
return res;*/
}

Lista<Hotel> Ministerio::listarhoteles(Cadena c, Lista<Hotel> hs) const {
Lista<Hotel> res;
int i=0;
while (i<hs.longitud())
  {
      if((hs.iesimo(i)).cadena()==c)
      {
          res.agregarAtras(hs.iesimo(i));
      }
      else
      {
      }
  i++;
  }
return res;
}

Lista<Hotel> Ministerio::todoshoteles() const{
Lista<Hotel> res;
int i=0;
while(i<_provincias.longitud())
   {
   res.concatenar(registro(_provincias.iesimo(i)));
   i++;
   }
res.cola();
return res;
  }

Lista<Cadena> Ministerio::listaCadenas(Lista<Hotel> hs) const{
Lista<Cadena> res;
int i=0;
while (i<hs.longitud())
   {
       res.agregarAtras((hs.iesimo(i)).cadena());
   i++;
   }
return res;
}

Lista<Hotel> Ministerio::sacarRepes(Lista<Hotel> hs) const{

	Lista<Hotel> res;
	int i=0;
	while (i < hs.longitud()) {

		if (!res.pertenece(hs.iesimo(i)))
		   res.agregarAtras(hs.iesimo(i));

	   i++;
	}

	return res;
}

void Ministerio::agregarHotel(const Hotel& h, const Provincia p) {
 pair<Provincia, Hotel> par;
 par.first=p;
 par.second=h;
 _registro.agregarAtras(par);
}

int minimo(Lista<int> xs){
int i=0;
int min=xs.iesimo(0);
while (i<xs.longitud())
  {
      if(xs.iesimo(i)<min)
      {
          min=xs.iesimo(i);
      }
      else
      {
      }
  i++;
  }
return min;
}

Lista<Cadena> Ministerio::cadenasAmarretas() const{
int i=0;
Lista<Cadena> res;
Lista<int> cants;
while (i<cadenasDeHoteles().longitud())
      {
         cants.agregarAtras(dameprovs(cadenasDeHoteles().iesimo(i)).longitud());
         i++;
      }
int min= minimo(cants);
int j=0;
while (j<cadenasDeHoteles().longitud())
   {
       if(min==(dameprovs(cadenasDeHoteles().iesimo(j))).longitud())
       {
           res.agregarAtras(((cadenasDeHoteles().iesimo(j)).iesimo(0)).cadena());
       }
       else{
       }
   j++;
   }
return res;
}


void Ministerio::fusionAutorizada(const Cadena c1, const Cadena c2) {

	Lista<pair<Provincia, Hotel> > registroNuevo;
	int i = 0;
	while (i < _registro.longitud()) {

		pair<Provincia, Hotel> registro = _registro.iesimo(i);
		Provincia provincia = registro.first;
		Hotel hotel = registro.second;

		if (hotel.cadena() == c2) {

			/*Hotel hotelNuevo = Hotel(hotel.nombre(),
					c2,
					hotel.habitaciones(),
					tipoHabitacionXDinero(hotel),
					accesoriosPorDinero(hotel));*/
			hotel.vender(c2);

			pair<Provincia, Hotel> entradaNueva;
			entradaNueva.first = provincia;
			entradaNueva.second = hotel;

			registroNuevo.agregarAtras(entradaNueva);
		} else {

			registroNuevo.agregarAtras(registro);
		}

		i++;
	}

	_registro = registroNuevo;
}

bool Ministerio::operator==(const Ministerio& m) const {

	return mismos(_provincias, m._provincias)
			&& mismos(_registro, m._registro);
}

void Ministerio::mostrar(std::ostream& os) const {

	os << ENCABEZADO_ARCHIVO;
	os << "[";
	int i = 0;
	while (i < _registro.longitud()) {

		pair<Provincia, Hotel> registro = _registro.iesimo(i);
		os << "(|" << registro.first << "|,";
		registro.second.mostrar(os);
		os << ")";

		i++;

		if (i < _registro.longitud())
			os << ",";
	}

	os << "]";
}

void Ministerio::guardar(std::ostream& os) const {

	mostrar(os);
}

void Ministerio::cargar (std::istream& is) {

	char x;
	is >> x; // encabezado
	is >> x; // "["
	while (x != ']') {

		pair<Provincia, Hotel> registro;
		string provincia;
		Hotel hotel;

		is >> x; // |
		getline(is, provincia, '|');
		hotel.cargar(is);

		registro.first = provincia;
		registro.second = hotel;
		_registro.agregar(registro);

		is >> x;
	}
}

/**********************
 * Funciones privadas *
 **********************/

template<class T> bool Ministerio::mismos(const Lista<T>& l1, const Lista<T>& l2) const {

	int i = 0;
	while (i < l1.longitud()) {
		if (!l2.pertenece(l1.iesimo(i)))
			return false;

		i++;
	}

	return true;
}


Lista<Provincia> Ministerio::dameprovs(Lista<Hotel> hs) const {
int i=0;
Lista<Provincia> res;
while (i<hs.longitud())
 {
     res.agregarAtras(prov(hs.iesimo(i)));
     i++;
 }
}

Provincia Ministerio::prov(Hotel h) const{

	int i = 0;
	while (i < _registro.longitud()) {

		if (h == _registro.iesimo(i).second)
			return _registro.iesimo(i).first;

		i++;
	}
}

Lista<pair<TipoHabitacion, Dinero> > Ministerio::tipoHabitacionXDinero(Hotel hotel) {

	Lista<pair<TipoHabitacion, Dinero> > lista;
	lista.agregarAtras(pair<TipoHabitacion, Dinero>(Simple, hotel.tarifaXDia(Simple)));
	lista.agregarAtras(pair<TipoHabitacion, Dinero>(Doble, hotel.tarifaXDia(Doble)));
	lista.agregarAtras(pair<TipoHabitacion, Dinero>(Triple, hotel.tarifaXDia(Triple)));
	lista.agregarAtras(pair<TipoHabitacion, Dinero>(Cuadruple, hotel.tarifaXDia(Cuadruple)));

	return lista;
}

Lista<pair<Accesorio, Dinero> > Ministerio::accesoriosPorDinero(Hotel hotel) {

	Lista<pair<Accesorio, Dinero> > lista;
	lista.agregarAtras(pair<Accesorio, Dinero>(Jacuzzi, hotel.precioAccesorio(Jacuzzi)));
	lista.agregarAtras(pair<Accesorio, Dinero>(LCD, hotel.precioAccesorio(LCD)));
	lista.agregarAtras(pair<Accesorio, Dinero>(PS3, hotel.precioAccesorio(PS3)));
	lista.agregarAtras(pair<Accesorio, Dinero>(DVD, hotel.precioAccesorio(DVD)));
	lista.agregarAtras(pair<Accesorio, Dinero>(Pelotero, hotel.precioAccesorio(Pelotero)));
	lista.agregarAtras(pair<Accesorio, Dinero>(Inflable, hotel.precioAccesorio(Inflable)));

	return lista;
}
